package com.ve.compiler;

import android.content.Context;
import android.util.Log;

import com.jaredrummler.android.shell.CommandResult;
import com.jaredrummler.android.shell.Shell;

import java.io.File;

public class Compiler implements Shell.Console.OnCloseListener {
    private static final String TAG = Compiler.class.getSimpleName();
    private Shell.Console console;
    private boolean isBooted = false;
    private ProgressListener progressListener = new ProgressListener.LogProgressAdapter();
    private static Compiler compiler = new Compiler();

    public static Compiler getCompiler() {
        return compiler;
    }

    public void compile(Context context, File file) {
        if (!isBooted) {
            progressListener.onProgress("启动环境");
            boot(context);
        }
        file = new File(file.getAbsolutePath().replace("/storage/emulated/0", "/sdcard"));


        if (isMakeFile(file)) {
            progressListener.onProgress("以make方式编译中");
            shell("cd " + file.getParent());
            shell("make " + file.getAbsolutePath());
            progressListener.onSucceed("以make方式编译完成");
        } else {
            progressListener.onProgress("编译中");
            File outDir = new File(file.getParent(), "out");
            if (outDir.exists()) {
                outDir.delete();
            }
            outDir.mkdirs();
//        GFile outFile=new GFile(outDir,file.getName().replace(".c",".hex"));

            shell("cd " + outDir.getAbsolutePath());
            String result = shellr("sdcc " + file.getAbsolutePath());
            if (result != null) {
                progressListener.onFail(result, null);
                return;
            }

            String fileName = getFileName(file);
            {
                File ihx = new File(outDir, fileName + ".ihx");
                if (!ihx.exists()) {
                    progressListener.onFail("编译失败", null);
                    return;
                }
                File hex = new File(outDir, fileName + ".hex");
                shell(String.format("packihx %s > %s", ihx.getAbsolutePath(), hex.getAbsolutePath()));
                if (!hex.exists()) {
                    progressListener.onFail("编译失败", null);
                    return;
                }
                File bin = new File(outDir, fileName + ".bin");
                shell(String.format("makebin %s > %s", hex.getAbsolutePath(), bin.getAbsolutePath()));
                if (!bin.exists()) {
                    progressListener.onFail("编译失败", null);
                    return;
                }

                progressListener.onSucceed(hex.getAbsolutePath());
//                Toast.makeText(context, "编译 " + file + " 完成", Toast.LENGTH_SHORT).show();
            }
        }
    }

    public static boolean isMakeFile(File file) {
        String name = file.getName().toLowerCase();
        return name.equals("make") || name.equals("makefile");
    }


    private String shellr(String cmd) {
        Log.d(TAG, "shell: " + cmd);
        CommandResult result = console.run(cmd);
        if (!result.isSuccessful()) {
            String stderr = result.getStderr();
            Log.d(TAG, "err: " + stderr);
            return stderr;
        }
        return null;
    }

    public static String getFileName(File file) {
        String name = file.getName();
        int i = name.lastIndexOf(".");

        if (file.isHidden() || i <= 0) {
            return name;
        }
        return name.substring(0, i);
    }

    public void setProgressListener(ProgressListener progressListener) {
        this.progressListener = progressListener;
    }

    public Shell.Console getConsole() {
        return console;
    }

    public boolean isBooted() {
        return isBooted;
    }

    public void boot(Context context) {
        if (isBooted) {
            return;
        }
        try {
            console = new Shell.Console.Builder()
                    .useSH()
                    .setWatchdogTimeout(100 * 1000)
                    .setOnCloseListener(this)
                    .build();
            String installPath = (context.getFilesDir().getAbsolutePath());
            shell(String.format("export PREFIX=%s", installPath));
            shell("cd $PREFIX");
            String cmd = "./proot ";
            cmd += "-r rootfs ";
            cmd += "-b /sdcard ";
            cmd += "-w /root ";
            cmd += "/bin/busybox env -i ";
            cmd += "HOME=/root ";
            cmd += "PATH=$PATH:/bin:/sdcc/bin ";
            cmd += "LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/lib ";
            cmd += "LANG=C.UTF-8 ";
            cmd += "/bin/busybox sh --login ";
            shell(cmd);
            isBooted = true;
        } catch (Exception e) {
            e.printStackTrace();
            isBooted = false;
        }
    }

    @Override
    public void onClosed(Shell.Console console) {
        Log.e(TAG, "onClosed: ");
        isBooted = false;
    }

    private void shell(String cmd) {
        Log.d(TAG, "shell: " + cmd);
        CommandResult result = console.run(cmd);
        if (result.isSuccessful()) {
            Log.d(TAG, "out: " + result.getStdout());
        } else {
            String stderr = result.getStderr();
            Log.d(TAG, "err: " + stderr);
        }
    }
}
